#ifndef RPTREE_H
#define RPTREE_H

#include "RPTreeParam.h"
#include "NDArray.h"

#include <vector> //vector
#include <list> //list
#include <ostream> //ostream
#include <istream> //istream


using namespace std;

class RPLeaf;

class RPTree
{
	public:
		enum rule
		{
			none = -1,
			hyperplane = 0,
			distance_from_the_mean = 1
		};
		
	protected:
		vector<double> v;
		rule usedRule;
		double threshold;
		double mean;

		unsigned int depth;

		RPTree *left;
		RPTree *right;

		// Constructeur pour noeud intermédiaire
		RPTree( const RPTreeParam &param,
			vector<unsigned int> &dataIdx,
			list< list<unsigned int> > &leavesContent,
			unsigned int depth,
			unsigned int &id );

		// Initialiseur (factorise le code des constucteurs)
		void init( const RPTreeParam &param,
			   vector<unsigned int> &dataIdx,
			   list< list<unsigned int> > &leavesContent,
			   unsigned int &id );

	public:
		// Constructeur vide (pour l'héritage)
		RPTree();

		// Constructeur pour la racine
		RPTree( RPTreeParam &param,
			list< list<unsigned int> > &leavesContent );
		
		// Destructeur
		virtual ~RPTree();

		// Operateur de conversion vers string
		virtual operator string() const;

		// Sauvegarde de l'arbre
		virtual void save( ostream &out ) const;

		// Reconstruit l'arbre depuis une sauvegarde
		static RPTree* load( istream &in );

		// Test d'une valeur
		virtual unsigned int use(double *data) const;

		// Test d'une série de valeurs
		void use(const CVGreyc::NDArray::CArray<double>& ndArray, unsigned int* result) const;

		// Accéder à une feuille
		const RPLeaf *get_leaf_by_id(unsigned int id) const;

		// Accessors 
		vector<double> &get_v() {return v;}
		RPTree& get_left() {return *left;}
		RPTree& get_right() {return *right;}
		RPTree::rule get_usedRule() const { return usedRule; }
		double get_threshold() const { return threshold ;}
		double get_mean() const { return mean; }
		unsigned int get_dim() const { return v.size(); }
		unsigned int get_depth() const { return depth; }
};

#endif
